#include <stdlib.h>
#include <string.h>
#include "list.h"
#include "err.h"
#include "utils.h"

#ifdef __cplusplus
extern "C" {
#endif

/*********************| 内部数据结构 |*********************/
/* 数据节点 */
typedef struct node_t {
	void*		data;	/* 数据区域 */
	struct node_t*	next;	/* 下一个节点的索引 */
	size_t		bufidx;
}node_t,* node_p;

static bool		_list_buf_inited = false;
static node_t		_node_buf[LIST_NODE_BUF_SIZE];
static size_t		_node_buf_now = 0;
static size_t		_free_index_arr[LIST_NODE_BUF_SIZE];
/*********************| 内部方法 |*********************/

/**
 * @brief 生成新的节点
 */
static node_p node_buf_new()
{
	if (_node_buf_now >= LIST_NODE_BUF_SIZE)
		return NULL;
	node_p ret = &(_node_buf[_free_index_arr[_node_buf_now]]);
	ret->data = NULL;
	ret->next = NULL;
	++_node_buf_now;
	return ret;
}

static void node_buf_return(node_p p)
{
	--_node_buf_now;
	_free_index_arr[_node_buf_now] = p->bufidx;
}

/**
 * @brief 获取链表的尾巴
 * @flag 0 表示结尾，其它值表示位置n
 */
static node_p list_tail(list_t* p, size_t n)
{
	csberrno = CSBERR_NOERR;
	CSB_NO_ERR_RET(p && n <= p->size, CSBERR_PARAM, NULL);
	CSB_YES_RET(0 == p->size, NULL);
	node_p ret = p->head;
	if (!n) {
		while (ret && ret->next) {
			ret = ret->next;
		}
	} else {
		while (--n) {
			ret = ret->next;
		}
	}
	return ret;
}

/**
 * @brief 默认的比较函数
 */
static int default_node_data_cmp(void* pa, void* pb)
{
	return (size_t)pa - (size_t)pb;
}

/*********************| 外部接口 |*********************/

CSB_DLL void list_buf_init()
{
	if (!_list_buf_inited) {
		size_t i = 0;
		for (i = 0; i < LIST_NODE_BUF_SIZE; ++i) {
			_free_index_arr[i] = i;
			_node_buf[i].bufidx = i;
		}
		_list_buf_inited = true;
	}
}

CSB_DLL list_t*	list_new()
{
	list_t* ret = NULL;
	do {
		ret = (list_t*)malloc(sizeof(list_t));
	} while (!ret);
	list_init(ret);
	return ret;
}

CSB_DLL int list_foreach(list_t* pal, node_data_foreach func, void* ctlflag)
{
	CSB_NO_RET(pal && pal->size && func, CSBERR_PARAM);
	node_p pnode = pal->head;
	node_p ppre = pnode;
	node_p pnext = NULL;
	int ret = 0;
	while (pnode) {
		pnext = pnode->next;
		ret =func(&(pnode->data), ctlflag);
		if (2 == ret) {
			if (pnode == pal->head)
				pal->head = pnext;
			else
				ppre->next = pnext;
			node_buf_return(pnode);
			--pal->size;
		} else if(ret != 1) {
			return CSBERR_NOERR;
		} else {
			ppre = pnode;
		}
		pnode = pnext;
	}
	return CSBERR_NOERR;
}

CSB_DLL int list_clear(list_t* pal, free_node_data func)
{
	CSB_NO_RET(pal && pal->size, CSBERR_PARAM);
	node_p pnode = pal->head;
	node_p nenode = NULL;
	if (func) {
		while (pnode) {
			nenode = pnode->next;
			func(pnode->data);
			node_buf_return(pnode);
			pnode= nenode;
		}
	} else {
		while (pnode) {
			nenode = pnode->next;
			node_buf_return(pnode);
			pnode= nenode;
		}
	}
	pal->size = 0;
	pal->head = NULL;
	return CSBERR_NOERR;
}


CSB_DLL size_t list_insert(list_t* pal, void* data, size_t pos, const int istail)
{
	CSB_NO_RET(pal, CSBERR_PARAM);
	CSB_YES_RET(CSBERR_FINIAL == pal->size, CSBERR_FINIAL);
	node_p pnode = node_buf_new();
	if (!pnode) {
		printf("#####################################\n");
	}
	CSB_NO_RET(pnode, CSBERR_BUF_NOT_ENOUGH);
	pnode->data = data;
	node_p p = NULL;
	if (istail || pos >= pal->size) {
		p = list_tail(pal, 0);
		if (!p) {
			pal->head = pnode;
		} else {
			p->next = pnode;
		}
	} else {
		if (!pos) {
			pnode->next = pal->head;
			pal->head = pnode;
		} else {
			p = list_tail(pal, pos);
			pnode->next = p->next;
			p->next = pnode;
		}
	}
	++pal->size;
	return CSBERR_NOERR;
}

CSB_DLL size_t list_get(list_t* pal, size_t pos, void** out)
{
	CSB_NO_RET(pal && out && pal->size && pos < pal->size, CSBERR_PARAM);
	node_p pnode = list_tail(pal, pos + 1);
	/* 获取数据引用 */
	*out = (void*)(&(pnode->data));
	return CSBERR_NOERR;
}

CSB_DLL findRes_t* list_find(list_t* pal, void* data, node_data_cmp func)
{
	csberrno = CSBERR_NOERR;
	CSB_NO_ERR_RET(pal, CSBERR_PARAM, NULL);
	if (!func) {
		func = default_node_data_cmp;
	}
	node_p pnode = pal->head;
	size_t pos = 0;
	while (pnode) {
		if (func(pnode->data, data)) {
			pnode = pnode->next;
		} else {
			findRes_t* ret = NULL;
			do { ret = (findRes_t*)malloc(sizeof(findRes_t)); }while(!ret);
			ret->pos = pos;
			ret->datare = (void*)&pnode->data;
			return ret;
		}
		++pos;
	}
	return NULL;
}

CSB_DLL size_t list_del(list_t* pal, size_t pos, void** srcdata)
{
	CSB_NO_RET(pal && pal->size && pos < pal->size, CSBERR_PARAM);
	node_p pnode = pal->head;
	void* pdata = pnode->data;
	if (!pos) {
		pal->head = pnode->next;
		node_buf_return(pnode);
	} else {
		pnode = list_tail(pal, pos);
		node_p nenode = pnode->next;
		pdata = nenode->data;
		pnode->next = nenode->next;
		node_buf_return(nenode);
	}
	// 如果不关心数据的内存维护传递NULL
	if (srcdata) {
		*srcdata = pdata;
	}
	--pal->size;
	return CSBERR_NOERR;
}

CSB_DLL size_t list_finddel(list_t* pal, void* data, node_data_cmp func, void** srcdata)
{
	CSB_NO_RET(pal, CSBERR_PARAM);
	if (!func) {
		func = default_node_data_cmp;
	}
	node_p pnode = pal->head;
	node_p prenode = NULL;
	while (pnode) {
		if (func(pnode->data, data)) {
			prenode = pnode;
			pnode = prenode->next;
		} else {
			if (srcdata) {
				*srcdata = pnode->data;
			}
			if (pnode == pal->head) {
				pal->head = pnode->next;
			} else {
				prenode->next = pnode->next;
			}
			node_buf_return(pnode);
			return CSBERR_NOERR;
		}
	}
	return CSBERR_FINIAL;
}

#ifdef __cplusplus
} /* end extern C */
#endif
